package liquidfs.data;

import java.util.*;

import com.thoughtworks.xstream.annotations.*;

@XStreamAlias("host")
public class Host implements Comparable<Host> {

   @XStreamAsAttribute()
	private String name;
   
   @XStreamAsAttribute()
	private int port;
	
   @XStreamOmitField()
   private Date deadSince = null;
   
   @XStreamOmitField()
   private Date lastCommunication = null;
   
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getPort() {
		return port;
	}
	
	public void setPort(int port) {
		this.port = port;
	}

	public Host(String name, int port) {
		this.name = name;
		this.port = port;
	}
	
	public Host (String url) {
	   String[] parts = url.split(":");
	   
	   if (parts.length == 0)
	      throw new IllegalArgumentException("Cannot create Host from an empty string.");
	   
      this.name = parts[0];
      
      if (parts.length >= 2) {
         this.port = Integer.parseInt(parts[1]);
      }
	}
	
	public boolean presumedDown () {
	   return deadSince != null;
	}
	
	public synchronized boolean isWorthTrying () {
	   
	   // If the host was still up, last we knew, obviously we can try it
	   if (deadSince == null)
	      return true;
	   
	   // Check how long we waited last time, and wait n times that long this time
	   long timeToNextCheck = 2 * (lastCommunication.getTime() - deadSince.getTime());
	   
	   // Cap timeToNextCheck at 15 minutes
	   if (timeToNextCheck > 1000 * 60 * 15)
	      timeToNextCheck = (100 * 60 * 15);
	   
	   // Check if it's been that long already
	   return (System.currentTimeMillis() > deadSince.getTime() + timeToNextCheck);
	}
	
	public synchronized void setLastCommunication(boolean successful) {
	   
	   // Set the time of the last communication to right now
	   lastCommunication = new Date();
	   
	   // If it was successful, erase any previous indications of it being down
	   if (successful)
	      deadSince = null;
	   else if (deadSince == null)
	      deadSince = lastCommunication;
	}
	
	public String toString () {
		return this.name + ":" + this.port;
	}

   @Override
   public int compareTo(Host host) {
      return toString().compareTo(host.toString());
   }
	
}
